Raklion: fall and push of Selupan, skill multipliers, and the closed hatchery gate - #994
Merged
Merged
Conversation
…skills Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When Selupan appears, it falls from the sky and hits the players which are closer to it than four fields, like in the original game. The fall is a skill with a damage multiplier of 2.5, which is added to existing databases by a new update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Like in the original game, the fall pushes the hit players four fields away from Selupan, until a field isn't walkable or part of a safezone. Stunned and frozen players aren't pushed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Like in the original game, the ice strike (frost shock) of Selupan pushes the hit players ten fields away from Selupan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…inal In the original game, only dark knights, magic gladiators and dark lords are pushed by the full distance of the skills of Selupan, the other classes by two fields at most. The classes and the limit are configurable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Like in the original game, the gate to the hatchery doesn't move the player while the hatchery is closed, and shows that it's closed. Before, the player entered the hatchery and was moved to the start of raklion afterward. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ibutes The attribute system of a monster didn't support attribute relationships. So the first attack of Selupan with each of its skills threw an exception, and the skill attributes were cached without the damage multiplier. The monster now returns its attributes for the relationships of a skill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The game client shows its loading screen after it entered a gate, until a map change is completed. A failed map change doesn't end it, so the client got stuck. Like the original game, the player is warped to its current position instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sven-n
reviewed
Sep 28, 2026
sven-n
left a comment
Member
There was a problem hiding this comment.
Review
I read the whole diff and checked how it fits with the existing code. I also built it and ran the tests locally. The code looks good, and I have no blocking findings.
Verified
- The full solution builds with no errors, and the branch merges cleanly into current master.
MUnique.OpenMU.Tests(1077),Network.Packets.Tests(607) andPersistence.Initialization.Tests(32, 6 skipped) pass, including bothRaklionDataTestcases with the fall skill. MonsterAttributeHolder.GetOrCreateAttribute: good catch. #977 missed this:EnsureSkillAttributesassignsskillEntry.Attributesbefore it adds the relationships. So after theNotImplementedException, the cached entry had no multiplier for the rest of the battle. The fix resolves it for any monster that attacks with a skill that has relationships.- Push classes:
{4, 6, 7, 12, 13, 16, 17}matchesCharacterClassNumber(DK/BK/BM, MG/DM, DL/LE). UpdateVersion120 with 119 unused: fine.DataUpdateServicefinds pending updates as "not installed" (a set difference), not "greater than the highest installed version". So #992 can still use 119 whenever it lands, and databases already at 120 will still get it.- Denied gate:
PlayerMapTransitions.WarpToAsyncdoes a full map change even on the same map, so the client's loading screen ends as described. PushAwayAsync: at map edgesCalculateTargetPointwraps the byte, but the index stays in range and those fields aren't walkable, so the push just stops.
Non-blocking suggestions
WarpGateActionnow depends onRaklionPlugIndirectly. It works, but it's a generic player action that now knows about one event. The next event with a closed gate (e.g. Imperial Guardian, Kanturu) would add anotherifhere. A small plug-in point would keepWarpGateActionindependent, e.g. anIWarpGateEnterRestrictionPlugInwithValueTask<bool> CanEnterAsync(Player, ExitGate), whichRaklionPlugInimplements. That can be a follow-up.GetOrCreateAttributereturns a snapshot for monster attributes that nothing has changed yet. A relationship created from thatConstantElementwon't see elements added to that attribute later, becauseAddElementthen creates a newComposableAttribute. It's harmless forSkillMultipliertoday, since nothing changes it at runtime, but the<remarks>should say so, so nobody relies on it for dynamic stats.- The only change in
RaklionBoss.csis an added blank line. It's harmless, but it could be dropped to keep the diff focused.
CI: Codacy passes. Azure again "completed" the same second it started, which is the known infrastructure issue.
This looks ready to merge from my side.
Generated by Claude Code
Member
|
Please fix at least the first suggestion. |
…n point WarpGateAction no longer depends on the raklion event. The new plugin point IWarpGateEnteringPlugIn lets any plugin deny the entrance through a gate by cancelling it; RaklionPlugIn implements it for the closed hatchery. Also documents that GetOrCreateAttribute of a monster returns a snapshot for attributes which have no elements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Thanks for the review! Addressed in 888475c:
🤖 Generated with Claude Code |
Member
|
Re-checked
Verified
Looks good to merge from my side. Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up of #977.
Summary
@ze-dom confirmed in #977 that Selupan hits players when it falls from the sky at the start of the battle (video). Until now, the fall was only the animation of its appearance: it dealt no damage and pushed nobody.
This PR adds:
It also fixes two things:
Behaviour of the original game
The known server sources (IGCN, MuEmu, kessiler) agree on this behaviour:
FirstSkill) is used exactly once, at the first step of the battle. It uses skill 253 with the monster skill unit 37 ("Selupan - Fall"). The unit hits every player closer to Selupan than 4 fields (ScopeType 0,ScopeValue 4), measured from Selupan, not from its target. The damage multiplier is 2.5, as @ze-dom pointed out.gObjBackSpring2) moves each hit player away from Selupan, field by field. The fall pushes by 4 fields (element 51), the frost shock by 10 (element 50). The push stops at fields which aren't walkable, including the safezone. Stunned and frozen players aren't pushed.gObjBackSpring2.Two details are intentionally left out:
Changes
SelupanIntelligence:FallRadius. It still shows the fall animation as before. The damage uses the new skillSelupan Fall(253), so its multiplier applies, like the other attack skills of Selupan.PushAwayAsync). The push works like the one of Earthshake: it usesPlayer.MoveAsync, so the clients are updated.RaklionEventDefinition, new settings:FallRadius(4);FallPushDistance(4);IceStrikePushDistance(10);LimitedPushDistance(2);FullyPushedCharacterClassNumbers(the dark knight, magic gladiator and dark lord classes);GetPushDistance(...), which applies the per-class limit.WarpGateAction: before the warp, it calls the new plugin pointIWarpGateEnteringPlugIn, which can deny the entrance by cancelling it.RaklionPlugInimplements it:RaklionContext.CanEnterThroughGateAsyncdenies the hatchery while it's closed and shows the message. SoWarpGateActiondoesn't know about any event, and other events with a closed map can use the same plugin point. Like the original game (MuEmu'sERROR_JUMP), a denied player is warped to its current position. A "map change failed" isn't enough, because the game client keeps showing its loading screen after it entered a gate until a map change is completed. Before, the player entered the closed hatchery, got the message and was moved to the start of Raklion by the next tick.MonsterAttributeHolder.GetOrCreateAttribute: this threw aNotImplementedException. When Selupan attacked with a skill,EnsureSkillAttributesfailed while adding the relationship of the damage multiplier, because the relationship needs theSkillMultiplierof the monster. The skill attributes were already assigned to theSkillEntryat that point, so every later attack used them without the multiplier. The monster now returns its composed attribute if elements were added to it, and a constant element of its stat value otherwise.SkillNumber.SelupanFall = 253;InputOperator.Maximumlike the other three) for new databases;AddSelupanFallSkillUpdatePlugInfor existing ones. It reusesAddRaklionEventUpdatePlugIn.CreateSkill, and applying it twice changes nothing.Update version: this uses
UpdateVersion120, because 119 is used by the Imperial Guardian event in #992. If this is merged first, I'll renumber it.Tests
SelupanIntelligenceTest:NotImplementedExceptionbefore);RaklionEventDefinitionTest: the push distance of each character class.RaklionHatcheryGateTest: the closed hatchery can't be entered through a gate, other maps can, and the plugin denies nothing while the event isn't running.RaklionDataTestnow also covers the fall skill and its multiplier, for a new database and for the updates applied twice.Built with
-p:ci=true; all four test suites pass. Tested in game: the fall hits and pushes the players around Selupan. The exception of the multiplier was found in the server log of that test.🤖 Generated with Claude Code